﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using SynqIt;

namespace FBEntities
{
    public enum HttpVerb
    {
        GET,
        POST,
        DELETE
    }
    public class WebDownloader
    {

        private static string userAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; InfoPath.2; MS-RTC LM 8; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)";

        public static Int32 LoginTimeOut = 60000; // one minute 

        public static string PostData(string url, string poststring)
        {
            CookieManager cookieManager = new CookieManager();
            return PostData(url, poststring, cookieManager);
        }

        public static string PostData(string url, string poststring, CookieManager cookieManager)
        {
            if (string.IsNullOrEmpty(poststring))
                return null;

            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
            cookieManager.PublishCookies(httpRequest);

            httpRequest.Method = "POST";
            httpRequest.ContentType = "application/x-www-form-urlencoded";
            httpRequest.UserAgent = userAgent;
            httpRequest.AllowAutoRedirect = true;
            httpRequest.AllowWriteStreamBuffering = true;
            httpRequest.Proxy = null;

            byte[] bytedata = Encoding.UTF8.GetBytes(poststring);
            httpRequest.ContentLength = bytedata.Length;

            Stream requestStream = httpRequest.GetRequestStream();
            requestStream.Write(bytedata, 0, bytedata.Length);
            requestStream.Close();


            HttpWebResponse httpWebResponse = null;

            try
            {
                httpWebResponse = (HttpWebResponse)httpRequest.GetResponse();
            }
            catch (WebException ex)
            {
            }

            if (httpWebResponse != null)
                cookieManager.StoreCookies(httpWebResponse);
            else
                return "";

            string ret = "";
            Stream dataStream = httpWebResponse.GetResponseStream();
            StreamReader reader = new StreamReader(dataStream);

            ret = reader.ReadToEnd();
            return ret;
        }

        public static HttpWebResponse GetRawResponse(string url, CookieManager cookieManager)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
                request.UserAgent = userAgent;
                request.Timeout = LoginTimeOut / 4;
                request.Method = "GET";
                request.Proxy = null;
                cookieManager.PublishCookies(request);

                return (HttpWebResponse)request.GetResponse();

            }
            catch (Exception e)
            {
                try
                {
                    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
                    request.UserAgent = userAgent;
                    request.Timeout = LoginTimeOut;
                    request.Method = "GET";
                    cookieManager.PublishCookies(request);

                    return (HttpWebResponse)request.GetResponse();

                }
                catch (Exception ex)
                {
                    //MessageBox.Show(ex.Message);
                }

            }

            return null;
        }

        /// <summary>
        /// Downloads a JSON string from a given URL.
        /// </summary>
        /// <param name="url">The URL for the JSON object.</param>
        /// <returns>A string in JSON notation.</returns>
        public static string DownloadJSON(string url)
        {
            return DownloadJSON(url, new CookieManager());
        }

        public static string DownloadJSON(string url, CookieManager cookieManager)
        {
            string ret = "";
            try
            {
                HttpWebResponse response = GetRawResponse(url, cookieManager);

                if (response != null)
                    cookieManager.StoreCookies(response);
                Stream dataStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(dataStream);

                ret = reader.ReadToEnd();

                reader.Close();
                dataStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
            }

            return ret;
        }

        public static string DownloadHTML(string url)
        {
            return DownloadJSON(url, new CookieManager());
        }

        public static string DownloadHTML(string url, CookieManager cookieManager)
        {
            return DownloadJSON(url, cookieManager);
        }

        public static bool DownloadImageFile(string filePath, string url)
        {
            FileStream fsFileStream = null;
            HttpWebRequest webRequest = null;
            HttpWebResponse webResponse = null;
            bool ret = false;

            try
            {
                byte[] BUFFER = new byte[307200]; // 300 KB
                webRequest = (HttpWebRequest)WebRequest.Create(url);
                webRequest.Method = "GET";
                webRequest.Timeout = 120000;
                webResponse = (HttpWebResponse)webRequest.GetResponse(); //Getting the response

                if (webResponse.StatusCode.ToString().Equals("OK"))
                {
                    Stream responseStream = webResponse.GetResponseStream();
                    Stream ToStream = null;

                    try
                    {
                        if (File.Exists(filePath))
                        {
                            File.Delete(filePath);
                        }

                        ToStream = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write);

                        int count = 1;

                        while (count != 0)
                        {
                            count = responseStream.Read(BUFFER, 0, BUFFER.Length);
                            ToStream.Write(BUFFER, 0, count);
                            ToStream.Flush();
                        }

                        ret = true;
                    }
                    catch (Exception exception)
                    {
                        //MessageBox.Show(exception.Message,"ERR_DIF_1");
                    }
                    finally
                    {
                        ToStream.Close();
                        ToStream = null;
                    }
                }
            }
            catch (Exception exp)
            {
                //MessageBox.Show(exp.Message,"ERR_DIF_2");
            }
            finally
            {
                if (fsFileStream != null)
                {
                    //Closing file stream
                    fsFileStream.Close();
                    fsFileStream = null;
                }
                if (webRequest != null)
                {
                    webRequest = null;
                }
                if (webResponse != null)
                {
                    webResponse.Close();
                    webResponse = null;
                }
            }

            return ret;
        }

        public static Stream DownloadImageFile(string url)
        {
            FileStream fsFileStream = null;
            HttpWebRequest webRequest = null;
            HttpWebResponse webResponse = null;
            Stream responseStream = null;

            try
            {
                byte[] BUFFER = new byte[307200]; // 300 KB
                webRequest = (HttpWebRequest)WebRequest.Create(url);
                webRequest.Method = "GET";
                webRequest.Timeout = 120000;
                webResponse = (HttpWebResponse)webRequest.GetResponse(); //Getting the response

                if (webResponse.StatusCode.ToString().Equals("OK"))
                {
                    responseStream = webResponse.GetResponseStream();
                }
            }
            catch (Exception exp) { }
            finally
            {
                if (fsFileStream != null)
                {
                    //Closing file stream
                    fsFileStream.Close();
                    fsFileStream = null;
                }
                if (webRequest != null)
                {
                    webRequest = null;
                }
                if (webResponse != null)
                {
                    webResponse.Close();
                    webResponse = null;
                }
            }

            return responseStream;
        }

        public static string MakeRequest(Uri url, HttpVerb httpVerb, Dictionary<string, string> args)
        {
            if (args != null && args.Keys.Count > 0 && httpVerb == HttpVerb.GET)
            {
                url = new Uri(url.ToString() + EncodeDictionary(args, true));
            }
            if (args == null)
                args = new Dictionary<string, string>();

            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            request.Method = httpVerb.ToString();
            request.UserAgent = userAgent;

            if (httpVerb == HttpVerb.POST || httpVerb == HttpVerb.DELETE)
            {
                string postData = EncodeDictionary(args, false);
                ASCIIEncoding encoding = new ASCIIEncoding();

                byte[] postDataBytes = encoding.GetBytes(postData);
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = postDataBytes.Length;
                request.Accept = @"image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/vnd.xfdl; version=""6.5.0"", application/x-shockwave-flash, */*";
                request.Method = httpVerb.ToString();
                request.KeepAlive = true;
                request.ProtocolVersion = new Version(1, 1);
                request.Headers.Add("Accept-Language: en-us");
                request.Headers.Add("Accept-Encoding: gzip, deflate");
                request.Headers.Add("Cache-Control: no-cache");
                request.Headers.Add("Cookie: x-referer=http%3A%2F%2Fwww.facebook.com%2Fpages%2FUser-agent%2F109494709068270%23%2Fpages%2FUser-agent%2F109494709068270; presence=DJ284648551BchADF284648553708BptMvisMblsMblcMsndPBbloMbvtMctMsbPBtA_7bQBfAnullBuctMsA0QBblADacMutMUQQQ; __utmc=87286159; e=n; cur_max_lag=20; datr=1276802242-530138985d652ef0cb744c03fb3dbd47c1d36f7cfcf32dcdc85fc; __utma=87286159.1999173777.1278009832.1284648512.1284656366.8; __utmz=87286159.1284656366.8.8.utmcsr=forum.developers.facebook.net|utmccn=(referral)|utmcmd=referral|utmcct=/viewtopic.php; m_user=8017126171%3A0%3A%3A0%3A6df2793f%3A1283891832; lu=ghUAhF2XyhYWpa5-s1JuFTaQ; c_user=17803113; sct=1283970853; sid=1; xs=ff3b5c0e8000dfb866c9b588e2a140c1");
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(postDataBytes, 0, postDataBytes.Length);
                requestStream.Close();
            }

            try
            {
                using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream());
                    return reader.ReadToEnd();
                }
            }
            catch (WebException e)
            {
                string error = new StreamReader(e.Response.GetResponseStream()).ReadToEnd();
                return error;
            }
        }

        private static string EncodeDictionary(Dictionary<string, string> dict, bool questionMark)
        {
            StringBuilder sb = new StringBuilder();
            if (questionMark)
            {
                sb.Append("?");
            }
            foreach (KeyValuePair<string, string> kvp in dict)
            {
                sb.Append(HttpUtility.UrlEncode(kvp.Key));
                sb.Append("="); sb.Append(HttpUtility.UrlEncode(kvp.Value));
                sb.Append("&");
            }

            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }
    }
}
